package com.imast.android.bys.task;

import org.ksoap2.serialization.SoapObject;

import com.imast.android.bys.util.SoapClient;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;

public class SoapObjectTaskFragment extends Fragment {

	private SoapClient soapClient;

	public SoapClient getSoapClient() {
		return soapClient;
	}

	public void setSoapClient(SoapClient soapClient) {
		this.soapClient = soapClient;
	}

	/**
	 * Callback interface through which the fragment will report the task's
	 * progress and results back to the Activity.
	 */
	public static interface TaskCallbacks {
		void onPreExecute();

		void onProgressUpdate(int percent);

		void onCancelled();

		void onPostExecute(SoapObject soapObject);
	}

	private TaskCallbacks mCallbacks;
	private SoapObjectTask mTask;
	private boolean mRunning;
	
	@Override
	public void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		setTargetFragment(null, -1);
	}

	/**
	 * Hold a reference to the parent Activity so we can report the task's
	 * current progress and results. The Android framework will pass us a
	 * reference to the newly created Activity after each configuration change.
	 */
	@Override
	public void onAttach(Activity activity) {
		super.onAttach(activity);
		if (!(getTargetFragment() instanceof TaskCallbacks)) {
		      throw new IllegalStateException("Target fragment must implement the TaskCallbacks interface.");
		}
		mCallbacks = (TaskCallbacks) getTargetFragment();
	}

	/**
	 * This method will only be called once when the retained Fragment is first
	 * created.
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setRetainInstance(true);
	}
	
	@Override
	public void onDestroy() {
		super.onDestroy();
		cancel();
	}

	/**
	 * Set the callback to null so we don't accidentally leak the Activity
	 * instance.
	 */
	@Override
	public void onDetach() {
		super.onDetach();
		mCallbacks = null;
	}
	
	 /*****************************/
	  /***** TASK FRAGMENT API *****/
	  /*****************************/

	  /**
	   * Start the background task.
	   */
	  public void start() {
	    if (!mRunning) {
	      mTask = new SoapObjectTask();
	      mTask.execute(getSoapClient());
	      mRunning = true;
	    }
	  }

	  /**
	   * Cancel the background task.
	   */
	  public void cancel() {
	    if (mRunning) {
	      mTask.cancel(false);
	      mTask = null;
	      mRunning = false;
	    }
	  }

	  /**
	   * Returns the current state of the background task.
	   */
	  public boolean isRunning() {
	    return mRunning;
	  }

	/**
	 * A dummy task that performs some (dumb) background work and proxies
	 * progress updates and results back to the Activity.
	 * 
	 * Note that we need to check if the callbacks are null in each method in
	 * case they are invoked after the Activity's and Fragment's onDestroy()
	 * method have been called.
	 */
	private class SoapObjectTask extends
			AsyncTask<SoapClient, Integer, SoapObject> {
		
		private final String TAG = SoapObjectTask.class.getSimpleName();
		
		@Override
		protected void onPreExecute() {
			if (mCallbacks != null) {
				mCallbacks.onPreExecute();
				mRunning = true;
			}
			
		}

		/**
		 * Note that we do NOT call the callback object's methods directly from
		 * the background thread, as this could result in a race condition.
		 */
		@Override
		protected SoapObject doInBackground(SoapClient... params) {

			SoapClient soapClient = null;
			SoapObject response = null; 
			
			try {
				
				if (params[0] instanceof SoapClient) {
					soapClient = (SoapClient) params[0];
				}

				response = soapClient.makeCallSoapObject();
			} catch (Exception e) {
				// TODO: handle exception
			}
			
			return response;
		}

		@Override
		protected void onProgressUpdate(Integer... percent) {
			if (mCallbacks != null) {
				mCallbacks.onProgressUpdate(percent[0]);
			}
		}

		@Override
		protected void onCancelled() {
			if (mCallbacks != null) {
				mCallbacks.onCancelled();
				mRunning = false;
			}
		}

		@Override
		protected void onPostExecute(SoapObject soapObject) {
			if (mCallbacks != null) {
				mCallbacks.onPostExecute(soapObject);
				mRunning = false;
			}
		}
	}
}
